import time
import os
import random
import pygame
from Constants import *
import Dice
from threading import *
import sys
import XMLReader

running = True

class EventThread:
    def __init__(self):
        '''Thread.__init__(self);'''

    def start (self):
        self.run ()

    def run(self):

        def convert(number):
            if scanCode == 275:
                return 'r'
            elif scanCode == 276:
                return 'l'
            elif scanCode == 273:
                return 'u'
            elif scanCode == 274:
                return 'd'
            return ''

        lastMove=[]
        while(True):
            if(len(lastMove)==0):
                event = pygame.event.wait()
            else:
                if(pygame.event.peek([pygame.KEYUP, pygame.KEYDOWN])):                
                    event = pygame.event.wait()
            if(event.type == Constants.QUIT_EVENT):
                exit()
            if(event.type == pygame.KEYDOWN):
                scanCode = event.key
                c = convert(scanCode)
                if(c!='' and not c in lastMove):
                    lastMove.append(c)

            if(len(lastMove)>0):
                for move in lastMove:
                    Move(move)
 
            if(event.type == pygame.KEYUP):
                scanCode = event.key
                c = convert(scanCode)
                if(c in lastMove):lastMove.remove(c)
            time.sleep(0.01)



class FlipThread(Thread):
    def __init__(self):
        Thread.__init__(self);

    def run(self):
        while(running):
            pygame.display.flip()
            time.sleep(1.0/Constants.FRAME_RATE)
    


  # the player stub
class Player:
    def __init__(self, player):
        self.name = player[0]
        self.id = player[1]

    def Play(self, action, moves):
        if(action != None):
            if(action.question != None):
                print self.GetName(), " got question ", action.question
                a = random.sample(action.options,1)[0]
                print self.GetName(), " hmm... I think it is ", a
                return a
        return None 
    
    def Inform(self, message):
        pass
    
    def GetName(self):
        return self.name

    def GetId(self):
        return self.id;


class PlayerGUI(Player):
    def quit(self):
        pygame.event.post(pygame.event.Event(Constants.QUIT_EVENT,{}))
        self.flipThread.join()
        self.eventThread.join()

    def __init__(self, player):
        Player.__init__(self, player)      
        self.curInx = 1
        self.pawn = pygame.image.load(self.board.pawns[player[1]]) 
        PlayerGUI.register.append(self)
        self.MovePawn(0)


    def Inform(self, message):
        if(message.player == self.id):
            curtile = self.board.tiles[message.position]
            print curtile
            print self.cord
            if( int(curtile.x) != self.cord[0] or int(curtile.y) != self.cord[1] ):
                if(self.cord[0] == -1):return;
                value = self.GetCurrentTile().action.value
                if(message.code == 'MISS'):
                    self.MovePawn(-value)
                else:
                    self.MovePawn(value)

    def GetCord(self, index):
        current = "BEGIN"
        for i in range(index):
            current = self.board.path[current]
            if(current == 'END'):return (-1,-1)
        return (self.board.tiles[current].x, self.board.tiles[current].y)

    def GetCurrentTile(self):
        current = "BEGIN"
        for i in range(self.curInx):
            current = self.board.path[current]
            if(current == 'END'):None
        return self.board.tiles[current]         


    def MovePawn(self, move):   
        source = self.GetCord(self.curInx) 
        dest = self.GetCord(self.curInx+move)
        source = (int(source[0]), int(source[1]))
        dest = (int(dest[0]), int(dest[1]))
        self.curInx+=move
        desloc = (dest[0]-source[0],dest[1]-source[1])
        step=1.0/float(Constants.MOVE_FRAMES)
        
        rect = self.pawn.get_rect ()
        rect = rect.w / 2, rect.h / 2
        
        for i in range(Constants.MOVE_FRAMES):
            source = (source[0]+desloc[0]*step,source[1]+desloc[1]*step)            
            self.cord = (source[0], source[1])
            
            PlayerGUI.curPos = self.GuiPos ()
            screen.blit(PlayerGUI.bg, (0,0), pygame.Rect(PlayerGUI.curPos[0], PlayerGUI.curPos[1],PlayerGUI.w,PlayerGUI.h))

            for p in PlayerGUI.register:
                screen.blit(p.pawn, (p.cord[0]-PlayerGUI.curPos[0] -rect[0], p.cord[1]-PlayerGUI.curPos[1]-rect[1]))
            time.sleep(0.01)
            
        self.cord = (dest[0] , dest[1])
            
    def GuiPos (self):
        x = self.cord[0]
        y = self.cord[1]
        
        rect = screen.get_rect ()
        
        if x < rect.w / 2: vx = 0
        elif x > self.mapW - rect.w / 2: vx = self.mapW - rect.w
        else: vx = x - rect.w / 2
        
        if y < rect.h / 2: vy = 0
        elif y > self.mapH - rect.h / 2: vy = self.mapH - rect.h
        else: vy = y - rect.h / 2
        
        return [vx, vy]

    def ShowShuffle(self, moves):
        waitTime=0.1
        for i in range(5):        
            waitTime+=0.1
            r = random.randint(0,self.dice.faces-1)
            screen.blit(self.diceImg[r], (0,0));
            time.sleep(waitTime); 
        screen.blit(self.diceImg[moves-1], (0,0));

    def Play(self, action, moves):
        print 'my turn!'
        time.sleep(0.5)

        # animates the dice
        self.ShowShuffle(moves);
    
        # animates de moviment of the pawn
        for i in range(moves):
            self.MovePawn(1)
        self.lastMove = moves

	# prompts for input if necessary
        if(action != None):
            if(action.question != None):
                print self.GetName(), " got question ", action.question
                a = random.sample(action.options,1)[0]
                print self.GetName(), " hmm... I think it is ", a
                return a
        return None 

def Move(direction):
    if(direction ==  'r'):PlayerGUI.curPos[0]+=Constants.MOVE_STEP
    elif(direction ==  'l'):PlayerGUI.curPos[0]-=Constants.MOVE_STEP
    elif(direction ==  'u'):PlayerGUI.curPos[1]-=Constants.MOVE_STEP
    elif(direction ==  'd'):PlayerGUI.curPos[1]+=Constants.MOVE_STEP
    
    if(PlayerGUI.curPos[0]<0):PlayerGUI.curPos[0]=0
    elif(PlayerGUI.curPos[1]<0):PlayerGUI.curPos[1]=0
    elif(PlayerGUI.curPos[0]>PlayerGUI.mapW-PlayerGUI.w):PlayerGUI.curPos[0]=PlayerGUI.mapW-PlayerGUI.w
    elif(PlayerGUI.curPos[1]>PlayerGUI.mapH-PlayerGUI.h):PlayerGUI.curPos[1]=PlayerGUI.mapH-PlayerGUI.h

    screen.blit(PlayerGUI.bg, (0,0), pygame.Rect(PlayerGUI.curPos[0], PlayerGUI.curPos[1],PlayerGUI.w,PlayerGUI.h))
    for p in PlayerGUI.register: 
        screen.blit(p.pawn, (p.cord[0]-PlayerGUI.curPos[0], p.cord[1]-PlayerGUI.curPos[1]))

def BuildBackground(bg, over):
    PlayerGUI.mapW=bg.get_size()[0]
    PlayerGUI.mapH=bg.get_size()[1]
    for image in over:
        bg.blit(image[0],(image[1],image[2]))
    PlayerGUI.bg=bg


def LoadImages(boardxml,boardxsd,dice):
    # loading dice images
    diceBasePath = Constants.DICE_PATH
    PlayerGUI.diceImg=[diceBasePath.replace('#',str(d)) for d in range(1,dice.faces+1)]
    PlayerGUI.diceImg=[pygame.image.load(path) for path in PlayerGUI.diceImg]

    PlayerGUI.board = XMLReader.Loader(boardxml, boardxsd) 

    bgPath = PlayerGUI.board.bg
    bgPath = os.path.join (*bgPath.split ('/'))
    back = pygame.image.load(bgPath)
    over=[]
    for image in PlayerGUI.board.images:
        figPath = image[0]
        x = image[1]
        y = image[2]    
        over.append((pygame.image.load(figPath), int(x), int(y), 1.0, 1.0))
    #loading the board
    BuildBackground(back, over)


def Preload(dice, boardxml, boardXSD):
    PlayerGUI.register = []
    PlayerGUI.curPos = [0,0]
    PlayerGUI.w=Constants.RESOLUTIONW
    PlayerGUI.h=Constants.RESOLUTIONH
    pygame.init()
    global screen;screen  = pygame.display.set_mode((PlayerGUI.w,PlayerGUI.h))
    pygame.display.set_caption('Gepeto')
    PlayerGUI.dice=dice

    #loading images
    LoadImages(boardxml,boardXSD, PlayerGUI.dice)

    #start flip thread
    PlayerGUI.flipThread = FlipThread()
    PlayerGUI.flipThread.start()

    #start event thread
    PlayerGUI.eventThread = EventThread()
    #PlayerGUI.eventThread.start()

    Move('')

if __name__ == '__main__':
    xml = sys.argv[1]
    xsd = sys.argv[2]
    Preload(Dice.Dice(),  xml, xsd)
    p = PlayerGUI('fabio')
    p.ShowShuffle(2);

